package persistence;

import java.sql.*;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import model.Producto;

public class ProductoDAOJDBCImplementation implements ProductoDAO {

    private final Object lockOfTheConexion = new Object();
    private Connection conexion = null;
    private static ProductoDAOJDBCImplementation persistenceManager = null;
    private static final Logger logger = Logger.getLogger(ProductoDAOJDBCImplementation.class.getName());

    ProductoDAOJDBCImplementation() {
    }

    public static ProductoDAOJDBCImplementation getJDBCPersistenceManager() {
        if (persistenceManager == null) {
            persistenceManager = new ProductoDAOJDBCImplementation();
        }
        return persistenceManager;
    }

    @Override
    public boolean setUp(String url, String driver, String user, String password) {
        try {
            Class.forName(driver);
            conexion = DriverManager.getConnection(url, user, password);
        } catch (ClassNotFoundException ex) {
            logger.log(Level.SEVERE, "No se encontro el driver para la base de datos", ex);
            return false;
        } catch (SQLException ex) {
            logger.log(Level.SEVERE, "No se pudo establecer la conexion con la base de datos", ex);
            return false;
        }
        return true;
    }

    @Override
    public boolean disconnect() {
        try {
            conexion.close();
        } catch (SQLException ex) {
            logger.log(Level.SEVERE, "Conexi�n a la base de datos no cerrada", ex);
            return false;
        }
        return true;
    }

    @Override
    public boolean newProduct (Producto producto) {
        String query = "insert into\"PRODUCTOS\" values(?,?,?,?,?,?)";
        PreparedStatement statement;
        try {
            synchronized (lockOfTheConexion) {
                statement = conexion.prepareStatement(query);
            }
            statement.setString(1, producto.getNombre());
            statement.setString(2, producto.getDesCorta());
            statement.setString(3, producto.getDesLarga());
            statement.setInt(4, producto.getStock());
            statement.setDouble(5, producto.getPrecio());
            statement.execute();
            return true;
        } catch (SQLException ex) {
            logger.log(Level.SEVERE,  "Error al crear un producto", ex);
            return false;
        }
    }

    @Override
    public boolean deleteProduct(String name) {
        String query = "delete from \"PRODUCTOS\" where NAME = ?";
        PreparedStatement statement;
        try {
            synchronized (lockOfTheConexion) {
                statement = conexion.prepareStatement(query);
            }
            statement.setString(1, name);
            statement.execute();
            return true;
        } catch (SQLException ex) {
            logger.log(Level.SEVERE, "Error al borrar un amigo", ex);
            return false;
        }
    }

    @Override
    public boolean updateProduct(String name, Producto product) {
        String query = null;
        query = "update \"PRODUCTOS\" SET NAME =?,DESCORTA = ?,DESLARGA = ?,STOCK = ?,"
                + " PRECIO = ? where NAME = ?";
        PreparedStatement statement;
        try {
            synchronized (lockOfTheConexion) {
                statement = conexion.prepareStatement(query);
            }
            statement.setString(1, product.getNombre());
            statement.setString(2, product.getDesCorta());
            statement.setString(3, product.getDesLarga());
            statement.setInt(4, product.getStock());
            statement.setDouble(5, product.getPrecio());
            statement.setString(7, name);
            statement.execute();
            return true;
        } catch (SQLException ex) {
            logger.log(Level.SEVERE, "Error al actualizar un producto", ex);
            return false;
        }
    }

    @Override
    public Producto readProduct(String name) {
        String query = null;
        query = "select * from \"PRODUCTOS\" where NAME =?";
        PreparedStatement statement;
        ResultSet resultSet = null;
        Producto product = null;
        try {
            synchronized (lockOfTheConexion) {
                statement = conexion.prepareStatement(query);
            }
            statement.setString(1, name);
            resultSet = statement.executeQuery();
            if (resultSet.next()) {
                product = new Producto();
                product.setDesCorta(resultSet.getString("DESCORTA"));
                product.setDesLarga(resultSet.getString("DESLARGA"));
                product.setStock(resultSet.getInt("STOCK"));
                product.setNombre(resultSet.getString("NAME"));
                product.setPrecio(resultSet.getDouble("PRECIO"));
            }
        } catch (SQLException ex) {
            logger.log(Level.SEVERE, "Error al recuperar un producto", ex);
            product = null;

        } finally {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException ex) {
                    logger.log(Level.SEVERE, "Error al cerrar la conexon a la base de datos", ex);
                }
            }
        }
        return product;
    }

    public void setConnection(Connection conexion) {
        synchronized (lockOfTheConexion) {
            this.conexion = conexion;
        }
    }

    @Override
    public Map<String, Producto> getProductMap() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}